using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using TAAlert.CommonUtils;

namespace TAAlert.BackTest
{
    abstract class Strategy
    {
        private int startIxM;   // the first (price) index relevant for back-testing (less or equal to startDate)
        private int endIxM;     // the last (price) index relevant for back-testing (less or equal to endDate)
        private SortedList<DateTime, double> pricesM;   // dated close prices

        /// <summary>Constructor: Find array index of start and end date. Store common parameters</summary>
        /// <param name="startDate">Strategy start date</param>
        /// <param name="endDate">Strategy end date</param>
        /// <param name="prices">dated list of prices</param>
        /// <param name="trace">Child TraceSwitch</param>
        protected Strategy(DateTime startDate, DateTime endDate, SortedList<DateTime, double> prices, TraceSwitch trace)
        {
            this.Prices = prices;

            this.StartIx = this.Prices.IndexOfKey(startDate);
            if (this.StartIx == -1)
                this.StartIx = DateTimeUtil.ixOfLessOrEqual(this.Prices.Keys, startDate);

            this.EndIx = this.Prices.IndexOfKey(endDate);
            if (this.EndIx == -1)
                this.EndIx = DateTimeUtil.ixOfLessOrEqual(this.Prices.Keys, endDate);
            Debug.WriteLineIf(trace.TraceInfo, "Strategy: date[" + this.StartIx + "]=" + this.Prices.Keys[this.StartIx] + ", date[" + this.EndIx + "]=" + this.Prices.Keys[this.EndIx]);
            Debug.Assert(this.EndIx >= this.StartIx, "Strategy: endIx is less than startIx");
        }

        /// <summary>the first (price) index relevant for back-testing (less or equal to startDate))</summary>
        protected int StartIx
        {
            get { return this.startIxM; }
            private set { this.startIxM = value; }
        }

        /// <summary>the last (price) index relevant for back-testing (less or equal to endDate)</summary>
        protected int EndIx
        {
            get { return this.endIxM; }
            private set { this.endIxM = value; }
        }

        /// <summary>Readonly list of dated close prices</summary>
        protected SortedList<DateTime, double> Prices
        {
            get { return this.pricesM; }
            private set { this.pricesM = value; }
        }

        /// <summary>Generate list of investment positions. (+1 long, -1 short, 0 neutral)</summary>
        /// <returns>List of dated positions. The positions are established on date close and affect only the next day perofmrance.</returns>
        public abstract SortedList<DateTime, int> generate();
    }
}
